package com.yyge.util;

import cn.hutool.core.lang.UUID;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.yyge.context.JwtContext;
import com.yyge.context.RedisContext;
import com.yyge.dto.ResultCode;
import com.yyge.exception.ApplicationException;
import com.yyge.system.entity.SystemUser;
import com.yyge.vo.BeanConverter;
import com.yyge.vo.LoginUserVo;
import com.yyge.vo.LoginVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class AuthUtil {

    @Autowired
    private RedisContext redisContext;

    @Autowired
    private JwtContext jwtContext;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 存放登陆用户的信息
     */
    public ThreadLocal<SystemUser> loginVOThreadLocal = new ThreadLocal<>();


    /**
     * 创建登陆用户的koken
     * @param loginUser
     * @return
     */
    public String createToken(LoginUserVo loginUser) {
        //验证成功,生成UUID

        //生成UUID
        String uuid = UUID.fastUUID().toString();

        //JWT
        Map map=new HashMap();
        map.put("uuid",uuid);
        String token= JWTUtil.createToken(map,jwtContext.getKey().getBytes(StandardCharsets.UTF_8));


        //根据UUID获取redis中的key,格式:"back:jwt:"+UUID
        String redisKey=redisContext.getJWTKey(uuid);

        //redis中保存LoginVO

        //方案3:MapStruct
        SystemUser vo = BeanConverter.MAPPER.emp2LoginVO(loginUser);
        //给vo对象添加ip和ua
        vo.setIp(HttpUtil.getIp());
        vo.setUa(HttpUtil.getUA());


        //  LoginVO vo = new LoginVO();

        //设置账户类型 /*强制设置账户类型*/
        //vo.setAccountType(LoginVO.ACCOUNT_TYPE_ADMIN);

        //令牌过期时间(1小时后)
        vo.setExpiredTime(jwtContext.getExpires() + System.currentTimeMillis());

        //设置令牌
        vo.setToken(token);

        //保存到redis+jwt
        redisTemplate.opsForValue().set(redisKey,vo,jwtContext.getExpires(), TimeUnit.MILLISECONDS);

    return token;
    }


    /**
     * 通过持票人token获取LoginVO对象
     * @param auth
     * @return
     */
    public SystemUser getUser(String auth){

         //去除持票人的前缀
         //System.out.println(auth);
         auth=auth.replace("Bearer","").trim();

        //验证Token
        if(!(JWTUtil.verify(auth,jwtContext.getKey().getBytes(StandardCharsets.UTF_8)))){
            throw new ApplicationException(ResultCode.TOKEN_INVALID);
        }

        //解析令牌
        JWT jwt=JWTUtil.parseToken(auth);
        if (jwt==null) { /*token 错误*/ return null; }

        //获取令牌的UUID
        String uuid=jwt.getPayload("uuid").toString();

        //根据UUID构建Redis种保存LoginVO的key
        String key=redisContext.getJWTKey(uuid);

        //从Redis获取LoinVO

        SystemUser vo = (SystemUser) redisTemplate.opsForValue().get(key);
        if(vo==null){
            throw new ApplicationException(ResultCode.SYSTEM_TKOKEN_EXPIRES);
        }
        //判断是否过期
        if (System.currentTimeMillis() >= vo.getExpiredTime()) {
            return null;
        }

        //刷新令牌
        vo.setExpiredTime(System.currentTimeMillis() + jwtContext.getExpires());
        return vo;
    }

    /**
     * 获取到用户方便 Controller调用
     * @return 返回系统用户对象
     */
     public SystemUser getUser(){
        return this.loginVOThreadLocal.get();
     }



    /**
     * 删除Token
     * @return void
     */
   public void removeRedisToken(String auth){

        //去除持票人的前缀
         auth=auth.replace("Bearer","").trim();

        //验证Token
//      JWTUtil.parseToken(token);
        if(!(JWTUtil.verify(auth,jwtContext.getKey().getBytes(StandardCharsets.UTF_8)))){
            throw new ApplicationException(ResultCode.TOKEN_INVALID);
        }

        //解析令牌
        JWT jwt=JWTUtil.parseToken(auth);

        //获取令牌的UUID
        String uuid=jwt.getPayload("uuid").toString();

        //根据UUID构建Redis种保存LoginVO的key
        String key=redisContext.getJWTKey(uuid);
        Boolean delete = redisTemplate.delete(key);
        System.out.println("退出成功了么？"+delete);
   }
}
